package ndk.caro.views;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import ndk.caro.activities.R;
import ndk.caro.activities.myCaroActivity;
import ndk.caro.gameplays.myCaroGame;
import ndk.caro.gameplays.myPiece;
import ndk.caro.tools.myLine;
import ndk.caro.tools.myTool;

public class myCaroView extends View {
	public static int iEDGE_PIECE;
	public static int iEDGE_DEFAULT = 50;
	public static Rect RECT_LIMIT_DRAWING;
	public static int iSPACE_DRAWING_VS_MONITOR = 20;
	public static int iSPACE_ZOOM = 4;
	private static int iCOUNT_LIMIT_FOR_SELECT = 20;
	private static int iCOUNT_TOUCH_NONE = 0;

	private boolean bAllowDraw;
	private boolean bTouched = false;
	private float iX_CENTER_VIEW;
	private float iY_CENTER_VIEW;

	private int iCountTouched;

	private float iX_NewCenter;
	private float iY_NewCenter;

	private float fX_OldTouched;
	private float fY_OldTouched;

	private float fX_NewTouched;
	private float fY_NewTouched;

	public myCaroGame mCaroGame;
	private Point pointAfterTouchForPiece;
	private Point pointAfterTouchForDisplay;
	private TouchMode eTouchMode;
	private TouchMode eTouchModeSelect;
	private myLine mLine1;
	private myLine mLine2;
	public ArrayList<Point> arrLPieceSelected;
	public myCaroActivity actMain;
	public void setRectLimitDrawing() {
		RECT_LIMIT_DRAWING = new Rect(
				this.getLeft(),
				this.getTop(),
				this.getRight(),
				this.getBottom()
				);
	}
	
	public Point getPointAfterTouchForPiece() {
		return pointAfterTouchForPiece;
	}

	public void setPointAfterTouchForPiece(Point pointAfterTouchForPiece) {
		this.pointAfterTouchForPiece = pointAfterTouchForPiece;
	}

	public boolean isAllowDraw() {
		return bAllowDraw;
	}

	public void setAllowDraw(boolean bAllowDraw) {
		this.bAllowDraw = bAllowDraw;
	}

	public boolean isTouched() {
		return bTouched;
	}

	public void setTouched(boolean bTouched) {
		this.bTouched = bTouched;
	}
	
	public int getCountTouched() {
		return iCountTouched;
	}

	public void setCountTouched(int iCountTouched) {
		this.iCountTouched = iCountTouched;
	}

	public static int getMinEgde() {
		return RECT_LIMIT_DRAWING.height() / myCaroGame.iGAME_SIZE -1;		
	}
	
	public static int getMaxEdge() {

		return RECT_LIMIT_DRAWING.height() / 3;
	}

	public void setDefaulEgde() {
		iEDGE_PIECE = getDefaultEdge();
		this.setNewCenter(iX_CENTER_VIEW, iY_CENTER_VIEW);	
	}
	
	public static int getDefaultEdge() {
		return RECT_LIMIT_DRAWING.height() / 10;
	}

	public static void setZoomAdd(int iValue) {
		iEDGE_PIECE = iEDGE_PIECE + iValue;
	}

	public static void setZoomDec(int iValue) {
		iEDGE_PIECE = iEDGE_PIECE - iValue;
	}

	public TouchMode getTouchModeSelect() {
		return eTouchModeSelect;
	}

	public void setTouchModeSelect(TouchMode eTouchModeSelect) {
		this.eTouchModeSelect = eTouchModeSelect;
	}

	public void setTouchmode(TouchMode eValue) {
		this.eTouchMode = eValue;
	}

	public TouchMode getTouchmode() {
		return this.eTouchMode;
	}

	public static int getEdge_Piece() {
		return iEDGE_PIECE;
	}

	public static void setEdge_Piece(int iEDGE_PIECE) {
		myCaroView.iEDGE_PIECE = iEDGE_PIECE;
	}

	public void setNewCenter(float iX_NewCenter, float iY_NewCenter) {
		this.iX_NewCenter = iX_NewCenter;
		this.iY_NewCenter = iY_NewCenter;
	}

	public float getX_NewCenter() {
		return iX_NewCenter;
	}

	public float getY_NewCenter() {
		return iY_NewCenter;
	}

	public myCaroView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.actMain = (myCaroActivity)context;
	}

	public void init() {
		this.arrLPieceSelected = new ArrayList<Point>();
	
		this.setCountTouched(iCOUNT_TOUCH_NONE);
	
		this.setRectLimitDrawing();
		this.mCaroGame = new myCaroGame(this);	
		myCaroView.setEdge_Piece(getDefaultEdge());
		this.setTouchmode(TouchMode.DEFAULT);
		// Ve lai View
		this.invalidate();

		this.iX_CENTER_VIEW = RECT_LIMIT_DRAWING.width() / 2 + iEDGE_PIECE;
		this.iY_CENTER_VIEW = RECT_LIMIT_DRAWING.height() / 2 + iEDGE_PIECE;

		this.iX_NewCenter = this.iX_CENTER_VIEW;
		this.iY_NewCenter = this.iY_CENTER_VIEW;	
	}

	@Override
	protected void onDraw(Canvas canvas) {
		if (this.bAllowDraw) {
			this.drawLines(canvas);
			//this.drawLineCenter(canvas);

			// De sau -> khong dc xoa
			if (this.bTouched) {
				this.drawBmp(canvas);
			}		
		}
		super.onDraw(canvas);
	}

	private void drawLines(Canvas canvas) {
		Paint p = new Paint();
		p.setColor(getResources().getColor(R.color.lines));//

		// Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

		// Ve truc toa do - tung do :
		if (iX_NewCenter > RECT_LIMIT_DRAWING.left) {
			canvas.drawLine(iX_NewCenter, RECT_LIMIT_DRAWING.top, iX_NewCenter,
					RECT_LIMIT_DRAWING.bottom, p);
		}

		// Ve truc toa do - truc hoanh:
		if (iY_NewCenter > RECT_LIMIT_DRAWING.top) {
			canvas.drawLine(RECT_LIMIT_DRAWING.left, iY_NewCenter,
					RECT_LIMIT_DRAWING.right, iY_NewCenter, p);
		}

		for (int i = 1; i <= myCaroGame.iGAME_CENTER_ARRAY_PIECE; i++) {

			// Ve cac truc song song vs truc tung
			if (iX_NewCenter - i * iEDGE_PIECE > RECT_LIMIT_DRAWING.left
					&& iX_NewCenter - i * iEDGE_PIECE < RECT_LIMIT_DRAWING.right) {
				canvas.drawLine(iX_NewCenter - i * iEDGE_PIECE,
						RECT_LIMIT_DRAWING.top, iX_NewCenter - i * iEDGE_PIECE,
						RECT_LIMIT_DRAWING.bottom, p);
			}

			if (iX_NewCenter + i * iEDGE_PIECE > RECT_LIMIT_DRAWING.left
					&& iX_NewCenter + i * iEDGE_PIECE < RECT_LIMIT_DRAWING.right) {
				canvas.drawLine(iX_NewCenter + i * iEDGE_PIECE,
						RECT_LIMIT_DRAWING.top, iX_NewCenter + i * iEDGE_PIECE,
						RECT_LIMIT_DRAWING.bottom, p);
			}

			// Ve cac truc song song vs truc hoanh
			if (iY_NewCenter - i * iEDGE_PIECE > RECT_LIMIT_DRAWING.top
					&& iY_NewCenter - i * iEDGE_PIECE < RECT_LIMIT_DRAWING.bottom) {
				canvas.drawLine(RECT_LIMIT_DRAWING.left, iY_NewCenter - i
						* iEDGE_PIECE, RECT_LIMIT_DRAWING.right, iY_NewCenter
						- i * iEDGE_PIECE, p);
			}

			if (iY_NewCenter + i * iEDGE_PIECE > RECT_LIMIT_DRAWING.top
					&& iY_NewCenter + i * iEDGE_PIECE < RECT_LIMIT_DRAWING.bottom) {
				canvas.drawLine(RECT_LIMIT_DRAWING.left, iY_NewCenter + i
						* iEDGE_PIECE, RECT_LIMIT_DRAWING.right, iY_NewCenter
						+ i * iEDGE_PIECE, p);
			}
		}
	}

	private void drawBmp(Canvas canvas) {
		Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		for (int i = 0; i < this.arrLPieceSelected.size(); i++) {
			
			
			Point po = this.arrLPieceSelected.get(i);
			myPiece mp = this.mCaroGame.getPiece(po.x, po.y);
			//Log.i("NDK", po.x + "|" + po.y);
			PointF pf = mp.getPointOnDisplay(new PointF(this.iX_NewCenter,
					this.iY_NewCenter), iEDGE_PIECE);
			if (pf != null) {
				if(i == this.arrLPieceSelected.size()-1) {
					canvas.drawBitmap(this.setBmpForFirstPiece(this.mCaroGame.getPiece(
							po.x, po.y).getValue()), pf.x,pf.y, paint);
				} else {
					canvas.drawBitmap(this.setBmpForPiece(this.mCaroGame.getPiece(
						po.x, po.y).getValue()), pf.x, pf.y, paint);
				}
			}
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (this.bAllowDraw) {
			int actioncode = event.getAction();

			switch (actioncode) {
			case MotionEvent.ACTION_DOWN:
				this.fX_OldTouched = event.getX();
				this.fY_OldTouched = event.getY();
				this.setTouchmode(TouchMode.MOVE);
				this.setCountTouched(iCOUNT_TOUCH_NONE);
				this.setTouchModeSelect(TouchMode.SELECT);
				break;

			case MotionEvent.ACTION_UP:
				//Moi them:
				
				
				//-----------
				
				if (this.eTouchModeSelect == TouchMode.SELECT) {			
					this.mCaroGame.HandleTouchUp(event);									
					//Log.i("NDk", "ACTION_SELECT");
				}
				break;

			case MotionEvent.ACTION_POINTER_2_DOWN:				
				if (this.mLine1 != null) {
					this.mLine1 = null;
				}
				this.setTouchmode(TouchMode.ZOOM);

				PointF[] p = new PointF[2];
				for (int i = 0; i < 2; i++) {
					p[i] = new PointF(event.getX(i), event.getY(i));
				}

				this.mLine1 = new myLine(p[0], p[1]);
				p = null;

				break;

			case MotionEvent.ACTION_POINTER_2_UP:
				this.setTouchmode(TouchMode.DEFAULT);
				this.setTouchModeSelect(TouchMode.DEFAULT);
				this.setCountTouched(iCOUNT_LIMIT_FOR_SELECT);

				break;

			case MotionEvent.ACTION_MOVE:
				if (this.eTouchMode == TouchMode.ZOOM) {			
					if (this.mLine2 != null) {
						this.mLine2 = null;
					}
					PointF[] p1 = new PointF[2];
					for (int i = 0; i < 2; i++) {
						p1[i] = new PointF(event.getX(i), event.getY(i));
					}

					this.mLine2 = new myLine(p1[0], p1[1]);
					p1 = null;

					if (this.mLine1.Compare2Line(this.mLine2) == 1) {

						if(myCaroView.iEDGE_PIECE < myCaroView.getMaxEdge()) {
							myCaroView.setZoomAdd(iSPACE_ZOOM);
							this.invalidate();}
					} else if (this.mLine1.Compare2Line(this.mLine2) == -1) {
						if(myCaroView.iEDGE_PIECE > myCaroView.getMinEgde() && this.bCheckZoomDec()) {
							myCaroView.setZoomDec(iSPACE_ZOOM);
							this.invalidate(); }
					}

					this.iCountTouched = iCOUNT_LIMIT_FOR_SELECT;
					this.setTouchModeSelect(TouchMode.DEFAULT);
				} else if (this.eTouchMode == TouchMode.MOVE) {
					this.fX_NewTouched = event.getX();
					this.fY_NewTouched = event.getY();

					if (this.fX_NewTouched == this.fX_OldTouched
							&& this.fY_OldTouched == this.fY_NewTouched) {
						this.iCountTouched++;
						if (this.iCountTouched < iCOUNT_LIMIT_FOR_SELECT) {
							this.setTouchModeSelect(TouchMode.SELECT);
						}					
					} else if (this.fX_NewTouched != this.fX_OldTouched
							|| this.fY_OldTouched != this.fY_NewTouched) {
						this.TranlateNewCoordinate(this.fX_OldTouched,
								this.fY_OldTouched, this.fX_NewTouched,
								this.fY_NewTouched);

						this.iCountTouched = iCOUNT_LIMIT_FOR_SELECT;
						this.setTouchModeSelect(TouchMode.DEFAULT);

						this.invalidate();

						this.fX_OldTouched = event.getX();
						this.fY_OldTouched = event.getY();
					}
				}
				break;

			default:
				break;
			}
		}
		return true;
	}
	
	/*
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (this.bAllowDraw) {
			int actioncode = event.getAction();

			switch (actioncode) {
			case MotionEvent.ACTION_DOWN:
				this.fX_OldTouched = event.getX();
				this.fY_OldTouched = event.getY();
				this.setTouchmode(TouchMode.MOVE);
				this.setCountTouched(iCOUNT_TOUCH_NONE);
				this.setTouchModeSelect(TouchMode.SELECT);
				break;

			case MotionEvent.ACTION_UP:
				//Moi them:
				
				
				//-----------
				
				if (this.eTouchModeSelect == TouchMode.SELECT) {			
							this.mCaroGame.HandleTouchUp(event);									
					Log.i(myDetails.tag, "ACTION_SELECT");
				}
				break;

			case MotionEvent.ACTION_POINTER_2_DOWN:				
				if (this.mLine1 != null) {
					this.mLine1 = null;
				}
				this.setTouchmode(TouchMode.ZOOM);

				PointF[] p = new PointF[2];
				for (int i = 0; i < 2; i++) {
					p[i] = new PointF(event.getX(i), event.getY(i));
				}

				this.mLine1 = new myLine(p[0], p[1]);
				p = null;

				break;

			case MotionEvent.ACTION_POINTER_2_UP:
				this.setTouchmode(TouchMode.DEFAULT);
				this.setTouchModeSelect(TouchMode.DEFAULT);
				this.setCountTouched(iCOUNT_LIMIT_FOR_SELECT);

				break;

			case MotionEvent.ACTION_MOVE:
				if (this.eTouchMode == TouchMode.ZOOM) {			
					if (this.mLine2 != null) {
						this.mLine2 = null;
					}
					PointF[] p1 = new PointF[2];
					for (int i = 0; i < 2; i++) {
						p1[i] = new PointF(event.getX(i), event.getY(i));
					}

					this.mLine2 = new myLine(p1[0], p1[1]);
					p1 = null;

					if (this.mLine1.Compare2Line(this.mLine2) == 1) {

						if(myCaroView.iEDGE_PIECE < myCaroView.getMaxEdge()) {
							myCaroView.setZoomAdd(iSPACE_ZOOM);
							this.invalidate();}
					} else if (this.mLine1.Compare2Line(this.mLine2) == -1) {
						if(myCaroView.iEDGE_PIECE > myCaroView.getMinEgde() && this.bCheckZoomDec()) {
							myCaroView.setZoomDec(iSPACE_ZOOM);
							this.invalidate(); }
					}

					this.iCountTouched = iCOUNT_LIMIT_FOR_SELECT;
					this.setTouchModeSelect(TouchMode.DEFAULT);
				} else if (this.eTouchMode == TouchMode.MOVE) {
					this.fX_NewTouched = event.getX();
					this.fY_NewTouched = event.getY();

					if (this.fX_NewTouched == this.fX_OldTouched
							&& this.fY_OldTouched == this.fY_NewTouched) {
						this.iCountTouched++;
						if (this.iCountTouched < iCOUNT_LIMIT_FOR_SELECT) {
							this.setTouchModeSelect(TouchMode.SELECT);
						}					
					} else if (this.fX_NewTouched != this.fX_OldTouched
							|| this.fY_OldTouched != this.fY_NewTouched) {
						this.TranlateNewToado(this.fX_OldTouched,
								this.fY_OldTouched, this.fX_NewTouched,
								this.fY_NewTouched);

						this.iCountTouched = iCOUNT_LIMIT_FOR_SELECT;
						this.setTouchModeSelect(TouchMode.DEFAULT);

						this.invalidate();

						this.fX_OldTouched = event.getX();
						this.fY_OldTouched = event.getY();
					}
				}
				break;

			default:
				break;
			}
		}
		return true;
	}
	
	*/

	public boolean bCheckZoomDec() {
		PointF plt = this.mCaroGame.getLeftTopPiece().getPointRealOfPiece(
				new PointF(this.iX_NewCenter,this.iY_NewCenter),
				iEDGE_PIECE - iSPACE_ZOOM
				);
		
		PointF prb = this.mCaroGame.getRightBottomPiece().getPointRealOfPiece(
				new PointF(this.iX_NewCenter,this.iY_NewCenter),
				iEDGE_PIECE  - iSPACE_ZOOM
				);	
		
		if(    plt.x < RECT_LIMIT_DRAWING.left + 2  
			&& prb.x > RECT_LIMIT_DRAWING.right + iEDGE_PIECE -2 
			&& plt.y < RECT_LIMIT_DRAWING.top + 2
		    && prb.y > RECT_LIMIT_DRAWING.bottom + iEDGE_PIECE -2
				) {
			return true;
		}
		
		return false;
	}
	
	public boolean bCheckMoveX(float fOldX, float fOldY, float fNewX,
			float fNewY) {
		PointF plt = this.mCaroGame.getLeftTopPiece().getPointRealOfPiece(
				new PointF(this.iX_NewCenter + fNewX - fOldX,this.iY_NewCenter + fNewY - fOldY),
				iEDGE_PIECE
				);
		

		PointF prb = this.mCaroGame.getRightBottomPiece().getPointRealOfPiece(
				new PointF(this.iX_NewCenter + fNewX - fOldX,this.iY_NewCenter + fNewY - fOldY),
				iEDGE_PIECE
				);			
		if (	   plt.x < RECT_LIMIT_DRAWING.left + 2  
				&& prb.x > RECT_LIMIT_DRAWING.right + iEDGE_PIECE -2
			) {
			return true;
		}
		return false;
	}
	
	public boolean bCheckMoveY(float fOldX, float fOldY, float fNewX,
			float fNewY) {
		PointF plt = this.mCaroGame.getLeftTopPiece().getPointRealOfPiece(
				new PointF(this.iX_NewCenter + fNewX - fOldX,this.iY_NewCenter + fNewY - fOldY), iEDGE_PIECE);		

		PointF prb = this.mCaroGame.getRightBottomPiece().getPointRealOfPiece(
				new PointF(this.iX_NewCenter + fNewX - fOldX,this.iY_NewCenter + fNewY - fOldY),iEDGE_PIECE);			
		if (	  plt.y < RECT_LIMIT_DRAWING.top + 2
				&& prb.y > RECT_LIMIT_DRAWING.bottom + iEDGE_PIECE - 2) {
			return true;
		}
		return false;
	}

	private void TranlateNewCoordinate(float fOldX, float fOldY, float fNewX,
			float fNewY) {		
		
		if(this.bCheckMoveX(fOldX, fOldY, fNewX, fNewY)) {
			this.iX_NewCenter += fNewX - fOldX;
		}
		if(this.bCheckMoveY(fOldX, fOldY, fNewX, fNewY)) {
			this.iY_NewCenter += fNewY - fOldY;
		}	
	}

	// 1. Thiet lap vi tri thuc cua X/O len ma hinh va cot/dong cua vien bi len
	// matran game:
	public void setPointAfterTouchDisplay(float fX, float fY) {
		int iX = (int) (fX > this.iX_NewCenter ? (fX - this.iX_NewCenter)
				/ iEDGE_PIECE : (this.iX_NewCenter - fX) / iEDGE_PIECE + 1);
		int iY = (int) (fY > this.iY_NewCenter ? (fY - this.iY_NewCenter)
				/ iEDGE_PIECE : (this.iY_NewCenter - fY) / iEDGE_PIECE + 1);

		int iX_lo = (int) (fX > this.iX_NewCenter ? this.iX_NewCenter + iX
				* iEDGE_PIECE : this.iX_NewCenter - iX * iEDGE_PIECE);
		int iY_lo = (int) (fY > this.iY_NewCenter ? this.iY_NewCenter + iY
				* iEDGE_PIECE : this.iY_NewCenter - iY * iEDGE_PIECE);

		this.pointAfterTouchForDisplay = new Point(iX_lo, iY_lo);	

		int iCol = fX > this.iX_NewCenter ? myCaroGame.iGAME_CENTER_ARRAY_PIECE
				+ iX : myCaroGame.iGAME_CENTER_ARRAY_PIECE - iX;
		int iRow = fY > this.iY_NewCenter ? myCaroGame.iGAME_CENTER_ARRAY_PIECE
				+ iY : myCaroGame.iGAME_CENTER_ARRAY_PIECE - iY;
	
		this.pointAfterTouchForPiece = new Point(iCol, iRow);
	}
	
	public Bitmap setBmpForFirstPiece(int iValue) {
		if(iValue == myPiece.iXPLAYER) {
			return myTool.resize(
					BitmapFactory.decodeResource(getResources(), R.drawable.xx),
					iEDGE_PIECE, iEDGE_PIECE);
		} else if(iValue == myPiece.iOPLAYER) {
			return myTool.resize(
					BitmapFactory.decodeResource(getResources(), R.drawable.oo),
					iEDGE_PIECE, iEDGE_PIECE);
		}
		return null;
	}
	
	
	public Bitmap setBmpForPiece(int iValue) {	
		
		if (iValue == myPiece.iXPLAYER) {
			return myTool.resize(
					BitmapFactory.decodeResource(getResources(), R.drawable.x),
					iEDGE_PIECE, iEDGE_PIECE);
		} else if (iValue == myPiece.iOPLAYER) {
			return myTool.resize(
					BitmapFactory.decodeResource(getResources(), R.drawable.o),
					iEDGE_PIECE, iEDGE_PIECE);
		}
		return null;
	}

	public enum TouchMode {
		SELECT, MOVE, ZOOM, DEFAULT
	}
		
}
